﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Configuration;
using System.Threading;
using System.Diagnostics;
using System.Security.AccessControl;

namespace SearchContent
{
    public partial class Form1 : Form
    {
        #region 参数
        string path = string.Empty;//要搜索的文件夹
        string keyword = string.Empty;//搜索的关键字
        //List<string> _filetype = new List<string>();//文件类型集合
        // List<string> filelist = new List<string>();//文件路径
        List<FilePath> filelist = new List<FilePath>();
        object objlockfilelist = new object();//文件集合锁
        object objlockfilepathappend = new object();//dataGridView锁 
        int _allnumber = 0;//文件总个数
        int _snumber = 0;//搜索的个数
        int _tnum = 1;//线程数
        int _num = 0;//命中文件个数 
        #endregion

        public Form1()
        {
            InitializeComponent();
        }

        //窗体加载监听参数
        private void Form1_Load(object sender, EventArgs e)
        {
            //开启线程监听文件个数
            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
            {
                try
                {
                    while (true)
                    {
                        this.Invoke(new Action(delegate()
                        {
                            this.toolStripStatusLabel8.Text = _allnumber.ToString();//文件总个数
                            this.toolStripStatusLabel9.Text = _snumber.ToString();//检索个数
                            int i = (_snumber == 0 ? 0 : (int)(_snumber * 100.0) / _allnumber);
                            this.toolStripProgressBar1.Value = i;//进度条
                            this.toolStripStatusLabel7.Text = string.Format("{0}%", i);//百分比
                            this.toolStripStatusLabel4.Text = _num.ToString();//命中文件
                        }));

                        Thread.Sleep(10);
                    }
                }
                catch
                {
                    // ignored
                }
            }), null);

            //

        }

        // 选择文件夹
        private void selectfolder_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrowserDialog fb = new FolderBrowserDialog();
                if (fb.ShowDialog() == DialogResult.OK)
                {
                    textBox2.Text = fb.SelectedPath;

                    _allnumber = _snumber = 0;
                    filelist.Clear();
                    dataGridView1.Rows.Clear();//清空显示
                    this.toolStripProgressBar1.Value = 0;
                    this.toolStripStatusLabel7.Text = @"0%";
                    this.toolStripStatusLabel4.Text = @"0";
                    _num = 0;

                    //开启一个线程去跑指定类型的文件路径
                    ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => { InitializeFileList(textBox2.Text, textBox3.Text.Split('|').ToList()); }), null);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //开始搜索
        private void SearchBtn_Click(object sender, EventArgs e)
        {
            #region 检查有效性
            path = textBox2.Text;
            keyword = keytext.Text;
            if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(keyword))
            {
                MessageBox.Show(@"不能为空");
                return;
            }

            if (!new DirectoryInfo(path).Exists)
            {
                MessageBox.Show(@"路径不存在");
                return;
            }
            #endregion

            dataGridView1.Rows.Clear();//清空显示

            int.TryParse(textBox1.Text, out _tnum);//线程个数

            if (_allnumber == _snumber)//_snumber：搜索的个数；_allnumber：文件总个数
            {
                _snumber = _num = 0;//_snumber:搜索个数;_num:命中个数

                filelist.ForEach(o => { o.Isvalid = true; });//设置全部未检索过
            }


            //执行搜索
            for (int i = 0; i < _tnum; i++)
            {
                ThreadPool.QueueUserWorkItem((obj) =>
                {
                    Console.WriteLine(string.Format("文件总个数:{0}----已搜索文件:{1}", _allnumber, _snumber));

                    while ((_allnumber - _snumber) > 0)
                    {
                        SearchContent(keyword, checkBox1.Checked);
                    }
                }, null);
            }
        }

        #region 搜索文件内容
        /// <summary>
        ///搜索文件内容
        /// </summary>
        /// <param name="keyword">关键字</param>
        /// <param name="b">是否区分大小写</param>
        /// <returns></returns>
        private void SearchContent(string keyword, bool b)
        {
            try
            {
                Thread.Sleep(100);
                string filepath = GetFilePath();

                if (string.IsNullOrEmpty(filepath))
                    return;

                string filecontent = File.ReadAllText(filepath, Encoding.Default);

                if (b)
                {//区分大小写 
                    if (filecontent.Contains(keyword))
                    {
                        AppendFileInfoToData(filepath);
                        //命中文件
                        _num += 1;
                    }
                }
                else
                {//不区分大小写
                    if (filecontent.ToLower().Contains(keyword.ToLower()))
                    {
                        AppendFileInfoToData(filepath);
                        //命中文件
                        _num += 1;
                    }
                }
            }
            catch
            {
                // ignored
            }
        }
        #endregion

        #region 添加到dataGridView
        /// <summary>
        /// 添加到dataGridView
        /// </summary>
        /// <param name="filepath"></param>
        public void AppendFileInfoToData(string filepath)
        {
            if (File.Exists(filepath))
            {
                FileInfo fi = new FileInfo(filepath);
                string size = (fi.Length / 1024.0).ToString();

                lock (objlockfilepathappend)
                {

                    this.Invoke(new Action(delegate()
                    {
                        dataGridView1.Rows.Add(filepath, size, fi.CreationTime.ToString(), fi.LastWriteTime.ToString(),"打开文件夹", "打开");
                    }));

                }
            }
        }
        #endregion

        #region 获取指定目录及子目录中所有文件列表
        /// <summary>
        /// 获取指定目录及子目录中所有文件列表
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。
        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
        private void InitializeFileList(string directoryPath, List<string> searchPattern)
        {
            //如果目录不存在，则抛出异常
            if (Directory.Exists(directoryPath))
            {
                //是否具有权限访问
                DirectorySecurity ds = new DirectorySecurity(directoryPath, AccessControlSections.Access);
                if (!ds.AreAccessRulesProtected)
                {
                    DirectoryInfo dir = new DirectoryInfo(directoryPath);

                    //是否存在文件夹
                    DirectoryInfo[] di = dir.GetDirectories();
                    if (di.Any())
                    {
                        foreach (var item in di)
                        {
                            InitializeFileList(item.FullName, searchPattern);
                        }
                    }

                    //是否存在文件
                    if (dir.GetFiles().Any())
                    {
                        //不同类型搜索文件
                        searchPattern.ForEach(e =>
                        {
                            FileInfo[] strlist = dir.GetFiles(e);
                            if (strlist.Any())
                            {
                                foreach (var val in strlist)
                                {
                                    AddMyList(val.FullName);
                                }
                            }

                        });
                    }
                }
            }
        }
        #endregion

        #region 打开文件
        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.RowIndex == -1 || e.ColumnIndex == -1)
                    return;

                object buttonText = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                if (buttonText != null)
                {

                    switch (buttonText.ToString())
                    {
                        case "打开":
                            Process.Start(this.dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString());
                            break;
                        case "打开文件夹"://打开文件夹并选中文件,
                            Process.Start("Explorer", "/select," + this.dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString());
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
        #endregion

        #region 添加文件到集合
        /// <summary>
        /// 添加文件集合
        /// </summary>
        /// <param name="path">文件路径</param>
        private void AddMyList(string path)
        {
            lock (objlockfilelist)
            {
                filelist.Add(new FilePath() { Value = path, Isvalid = true });
                _allnumber = filelist.Count();
            }
        }
        #endregion

        #region 获取一个路径
        /// <summary>
        /// 获取一个文件路径
        /// </summary>
        /// <returns></returns>
        private string GetFilePath()
        {
            lock (objlockfilelist)
            {
                var _mylist = filelist.FirstOrDefault(e => e.Isvalid);

                if (_mylist == null)
                {
                    return null;
                }

                filelist.Remove(_mylist);

                filelist.Add(new FilePath() { Value = _mylist.Value, Isvalid = false });

                _snumber = filelist.Count(e => !e.Isvalid);//使用个数

                return _mylist.Value;
            }
        }
        #endregion

        #region 对象
        /// <summary>
        /// 对象
        /// </summary>
        private class FilePath
        {
            /// <summary>
            /// 值
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// 是否有效
            /// </summary>
            public bool Isvalid { get; set; }
        }
        #endregion

        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            Rectangle rectangle = new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, dataGridView1.RowHeadersWidth - 4, e.RowBounds.Height);

            TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(), dataGridView1.RowHeadersDefaultCellStyle.Font, rectangle, dataGridView1.RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
        }

    }
}
